package org.stvd.service.quartz.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.quartz.Trigger.TriggerState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.stvd.common.SecurityUserHolder;
import org.stvd.common.utils.IdWorker;
import org.stvd.common.utils.ServiceResult;
import org.stvd.common.utils.StringsUtil;
import org.stvd.common.utils.VerifyUtil;
import org.stvd.core.dto.QueryResult;
import org.stvd.core.util.DateUtil;
import org.stvd.entities.quartz.QuartzJob;
import org.stvd.repository.quartz.QuartzJobDao;
import org.stvd.service.base.impl.BaseServiceImpl;
import org.stvd.service.quartz.QuartzJobService;

/**
 * @title QuartzJobServiceImpl
 * @description 定时任务业务层接口实现类
 * @auther houzx
 * @date 2022年03月10日
 */
@Service("QuartzJobService")
public class QuartzJobServiceImpl extends BaseServiceImpl<QuartzJob> implements QuartzJobService {

    @Resource(name = "QuartzJobDao")
    private QuartzJobDao quartzJobDao;

    @Autowired
    private QuartzHandler quartzHandler;

    @Override
    public QueryResult<QuartzJob> queryQuartzJobResult(int start, int limit, QuartzJob quartzJob) {
        QueryResult<QuartzJob> queryResult = quartzJobDao.queryQuartzJobResult(start, limit, quartzJob);
        for(QuartzJob job : queryResult.getRows()) {
            String status = quartzHandler.getStatus(job);
            if (!status.equals(job.getStatus())){
                job.setNextExecDate(quartzHandler.nextExecDate(job.getCronExpression()));
                job.setStatus(status);
                job.setModifyTime(DateUtil.getSystemDate());
                this.update(job);
            }
        }
        return queryResult;
    }
    
    @Override
    public List<QuartzJob> listEnabledQuartzJob() {
        return quartzJobDao.listEnabledQuartzJob();
    }

    @Override
    public ServiceResult<Map<String, Object>> insertQuartzJob(QuartzJob quartzJob) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
//        if (!VerifyUtil.isCron(quartzJob.getCronExpression())) {
//            serviceResult.setParamError("Cron表达式格式有误");
//            return serviceResult;
//        }
        try{
            Class.forName(quartzJob.getBeanClass());
        } catch (ClassNotFoundException exception) {
            serviceResult.setParamError("任务执行类不存在");
            return serviceResult;
        }
        if (StringsUtil.isNotEmpty(quartzJob.getJobDataMap())
             && !VerifyUtil.isJson(quartzJob.getJobDataMap())) {
            serviceResult.setParamError("任务参数格式有误");
            return serviceResult;
        }
        quartzJob.setId(IdWorker.getInstance().nextId());
        quartzJob.setCreateUser(SecurityUserHolder.getCurrentUserid());
        quartzJob.setCreateTime(DateUtil.getSystemDate());
        quartzJob.setStatus(TriggerState.NONE.toString());
        quartzJobDao.insert(quartzJob);
        serviceResult.setMessage("新增定时任务成功");
        return serviceResult;
    }

    @Override
    public ServiceResult<Map<String, Object>> updateQuartzJob(QuartzJob quartzJob) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
        quartzJob.setModifyTime(DateUtil.getSystemDate());
//        if (!VerifyUtil.isCron(quartzJob.getCronExpression())) {
//            serviceResult.setParamError("Cron表达式格式有误");
//            return serviceResult;
//        }
        if (StringsUtil.isNotEmpty(quartzJob.getJobDataMap())
                && !VerifyUtil.isJson(quartzJob.getJobDataMap())) {
            serviceResult.setParamError("任务参数格式有误");
            return serviceResult;
        }
        if (!(TriggerState.NONE.toString()).equals(quartzJob.getStatus())) {
            try {
                if (!quartzHandler.delete(quartzJob)) {
                    serviceResult.setParamError("定时任务更新失败");
                    return serviceResult;
                }
                Class<?> clazz = Class.forName(quartzJob.getBeanClass());
                if(!quartzHandler.start(quartzJob, clazz)){
                    serviceResult.setParamError("定时任务更新失败");
                    return serviceResult;
                }
            } catch (ClassNotFoundException e) {
                serviceResult.setParamError("定时任务执行类不存在");
                return serviceResult;
            }
        }
        quartzJob.setNextExecDate(quartzHandler.nextExecDate(quartzJob.getCronExpression()));
        quartzJob.setModifyTime(DateUtil.getSystemDate());
        quartzJobDao.update(quartzJob);
        serviceResult.setMessage("定时任务更新成功");
        return serviceResult;
    }

    @Override
    @Transactional
    public ServiceResult<Map<String, Object>> deleteQuartzJob(Long jobId) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
        QuartzJob quartzJob = quartzJobDao.findByPk(QuartzJob.class, jobId);
        if (quartzJob == null) {
            serviceResult.setParamError();
            return serviceResult;
        }
        if (!(TriggerState.NONE.toString()).equals(quartzJob.getStatus())) {
            if(!quartzHandler.delete(quartzJob)) {
                serviceResult.setSystemError("系统错误，定时任务删除失败");
                return serviceResult;
            }
        }
        quartzJobDao.delete(QuartzJob.class, jobId);
        serviceResult.setMessage("定时任务删除成功");
        return serviceResult;
    }

    @Override
    public ServiceResult<Map<String, Object>> startQuartzJob(Long jobId) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
        QuartzJob quartzJob = quartzJobDao.findByPk(QuartzJob.class, jobId);
        if (quartzJob == null) {
            serviceResult.setParamError();
            return serviceResult;
        }
        try{
            Class<?> clazz = Class.forName(quartzJob.getBeanClass());
            if (!quartzHandler.start(quartzJob, clazz)) {
                serviceResult.setSystemError("系统错误，定时任务启动失败");
                return serviceResult;
            }
        } catch (ClassNotFoundException ex) {
            serviceResult.setParamError("定时任务执行类不存在");
            return serviceResult;
        }
        serviceResult.setMessage("定时任务启动成功");
        return serviceResult;
    }

    @Override
    public ServiceResult<Map<String, Object>> pauseQuartzJob(Long jobId) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
        QuartzJob quartzJob = quartzJobDao.findByPk(QuartzJob.class, jobId);
        if (quartzJob == null) {
            serviceResult.setParamError();
            return serviceResult;
        }
        String status = quartzHandler.getStatus(quartzJob);
        if (!((TriggerState.NORMAL.toString()).equals(status)
                || (TriggerState.PAUSED.toString()).equals(status)
                || (TriggerState.BLOCKED.toString()).equals(status))) {
            serviceResult.setParamError("当前状态不可暂停");
            return serviceResult;
        }
        if (!quartzHandler.pause(quartzJob)) {
            serviceResult.setSystemError("系统错误，定时任务暂停失败");
            return serviceResult;
        }
        serviceResult.setMessage("定时任务暂停成功");
        return serviceResult;
    }

    @Override
    public ServiceResult<Map<String, Object>> executeQuartzJob(Long jobId) {
        ServiceResult<Map<String, Object>> serviceResult = new ServiceResult<Map<String, Object>>();
        QuartzJob quartzJob = quartzJobDao.findByPk(QuartzJob.class, jobId);
        if (quartzJob == null) {
            serviceResult.setParamError();
            return serviceResult;
        }
        String status = quartzHandler.getStatus(quartzJob);
        if (!((TriggerState.NORMAL.toString()).equals(status)
                || (TriggerState.PAUSED.toString()).equals(status)
                || (TriggerState.COMPLETE.toString()).equals(status))) {
            serviceResult.setParamError("当前状态不可立即运行");
            return serviceResult;
        }
        if (!quartzHandler.runOnce(quartzJob)) {
            serviceResult.setSystemError("系统错误，定时任务运行失败");
            return serviceResult;
        }
        serviceResult.setMessage("定时任务执行成功");
        return serviceResult;
    }
}
